#include <sourcemod>
#include <nextmap>
#include <sdkhooks>

#define INFOLEN 20
#define NAMELEN 20

public Plugin myinfo = 
{
	name = "BS Change MAP",
	author = "那一世的悲伤",
	description = "admin 换图",
	version = SOURCEMOD_VERSION,
	url = "http://www.sourcemod.net/"
};


StringMap maps;
StringMap mapNames;
Menu mapMenu;
Menu levelMenu;
char officalMapName[NAMELEN]="L4D2C";
ConVar bsMap;


public void OnPluginStart()
{
	bsMap = CreateConVar("bs_map", "", "存储下一关地图");
	RegAdminCmd("sm_mode", OnChangeMode, ADMFLAG_CHANGEMAP, "更换游戏模式");
	RegAdminCmd("sm_diff", OnChangeDiff,ADMFLAG_CHANGEMAP, "更换游戏难度");
	RegAdminCmd("sm_chmap", OnChangeMap,ADMFLAG_CHANGEMAP, "更换官方地图");
	RegAdminCmd("sm_chmap2", OnChangeMap2,ADMFLAG_CHANGEMAP, "更换三方地图");
	HookEvent("finale_win", OnFinaleWin);
	initMapNames();
	initMaps();
}


public void OnPluginEnd()
{
	delete maps;
	delete mapNames;
}

public void initMapNames()
{
	mapNames=new StringMap();
	mapNames.SetString("L4D2C1","死亡中心");
	mapNames.SetString("L4D2C2","黑暗嘉年华");
	mapNames.SetString("L4D2C3","沼泽激战");
	mapNames.SetString("L4D2C4","暴风骤雨");
	mapNames.SetString("L4D2C5","教区");
	mapNames.SetString("L4D2C6","短暂时刻");
	mapNames.SetString("L4D2C7","牺牲");
	mapNames.SetString("L4D2C8","毫不留情");
	mapNames.SetString("L4D2C9","坠机险途");
	mapNames.SetString("L4D2C10","死亡丧钟");
	mapNames.SetString("L4D2C11","静寂时分");
	mapNames.SetString("L4D2C12","血腥收获");
	mapNames.SetString("L4D2C13","刺骨寒溪");
	mapNames.SetString("L4D2C14","最后一战");

}

public void initMaps()
{
	maps=new StringMap();

	DirectoryListing dirList;
	KeyValues kv = new KeyValues("mission");
	dirList = OpenDirectory("missions", true, NULL_STRING);
	if (dirList == null) 
	{
        SetFailState("Could not locate mission folder");
	}
	else 
	{	
		char missionFileName[PLATFORM_MAX_PATH];
		char mapName[32];
		FileType fileType;
		while(dirList.GetNext(missionFileName, PLATFORM_MAX_PATH, fileType)) 
		{
			char missionPath[PLATFORM_MAX_PATH];
			Format(missionPath, PLATFORM_MAX_PATH, "missions/%s", missionFileName);
			if (fileType == FileType_File) 
			{
				if(strcmp("credits.txt", missionFileName, false) != 0)
				{
					kv.ImportFromFile(missionPath);
					kv.GetString("Name",mapName,sizeof(mapName));
					ArrayList missions=new ArrayList(100);
					char missionName[255];
					if (!kv.JumpToKey("modes"))
					{
						continue;	
					}
					if (!kv.JumpToKey("coop"))
					{
						continue;
					}
					if (!kv.GotoFirstSubKey(false))
					{
						continue;	
					}
					do
					{
						kv.GetString("Map",missionName,sizeof(missionName));
						missions.PushString(missionName);
					} while (kv.GotoNextKey());
					maps.SetValue(mapName,missions,true);
				}
			}	
		}
		delete dirList;
		delete kv;
	}
}

public Action OnChangeMode(int client, int args)
{
	if (args < 1)
	{
		PrintToChat(client, "\x04[提示]\x05!mode空格+模式(coop|realism|community1|community5|mutation4)");
		return Plugin_Handled;
	}
	char mode[64];
	GetCmdArgString(mode, sizeof(mode));
	SetConVarString(FindConVar("mp_gamemode"), mode);
	PrintToChatAll("\x04[提示]\x05当前模式已更换成\x04[\x03%s\x04]", mode)
	return Plugin_Handled;
}
public Action OnChangeDiff(int client,int args)
{
	if (args < 1)
	{
		PrintToChat(client, "\x04[提示]\x05!diff空格+难度(Easy|Normal|Hard|Impossible)");
		return Plugin_Handled;
	}
	char difficulty[64];
	GetCmdArgString(difficulty, sizeof(difficulty));
	SetConVarString(FindConVar("z_difficulty"), difficulty);
	PrintToChatAll("\x04[提示]\x05当前难度已更换成\x04[\x03%s\x04]", difficulty);
	return Plugin_Handled;
}

public Action OnChangeMap(int client,int args)
{
	mapMenu=new Menu(MapMenuHandler,MENU_ACTIONS_ALL);
	mapMenu.SetTitle("官方地图");
	StringMapSnapshot keys = maps.Snapshot();
	for (new i = 0; i < keys.Length; i++) {
		new size = keys.KeyBufferSize(i);
		char[] buffer = new char[size];
		keys.GetKey(i, buffer, size);
		if(StrContains(buffer, officalMapName, false) != -1)
		{
			mapMenu.AddItem(buffer,buffer);
		}
	}
	mapMenu.ExitButton=true;
	mapMenu.Display(client, MENU_TIME_FOREVER);
}

public Action OnChangeMap2(int client,int args)
{
	mapMenu=new Menu(MapMenuHandler,MENU_ACTIONS_ALL);
	mapMenu.SetTitle("三方地图");
	StringMapSnapshot keys = maps.Snapshot();
	for (new i = 0; i < keys.Length; i++) {
		new size = keys.KeyBufferSize(i);
		char[] buffer = new char[size];
		keys.GetKey(i, buffer, size);
		if(StrContains(buffer, officalMapName, false) == -1)
		{
			mapMenu.AddItem(buffer,buffer);
		}
	}
	mapMenu.ExitButton=true;
	mapMenu.Display(client, MENU_TIME_FOREVER);
}

public int MapMenuHandler(Menu menu, MenuAction action, int param1, int param2)
{
 	if(action == MenuAction_End) 
    {
		delete menu;
      	return 0;
    }
    char menuInfo[INFOLEN];	
	char menuName[NAMELEN]; 
	char missionName[NAMELEN];
	if(action == MenuAction_DisplayItem)
	{
		menu.GetItem(param2, menuInfo, sizeof(menuInfo), _, menuName, sizeof(menuName));
		char localizedName[NAMELEN];
		if(mapNames.GetString(menuName,localizedName,NAMELEN))
		{
			return RedrawMenuItem(localizedName);
		}
		return 0;
	}
 	else if(action == MenuAction_Select)	
    {
    	menu.GetItem(param2, menuInfo, sizeof(menuInfo), _, menuName, sizeof(menuName));
        levelMenu = new Menu(LevelMenuHandler);
	    levelMenu.SetTitle("请选择关卡");
	  	ArrayList missions;
	  	maps.GetValue(menuName,missions);
		int missionsLen = missions.Length;
	   	for(int i=0;i< missionsLen;i++)
		{
			IntToString(menu.Selection, menuInfo, sizeof(menuInfo));
		 	missions.GetString(i,missionName,sizeof(missionName));
			levelMenu.AddItem(menuInfo,missionName);
		}
		levelMenu.ExitButton = true;
		levelMenu.ExitBackButton = true;
		levelMenu.Display(param1, MENU_TIME_FOREVER);
	  }
    return 0;
}

public int LevelMenuHandler(Menu menu, MenuAction action, int param1, int param2)
{
	if (action == MenuAction_End) 
	{
		delete menu;
		return 0;
	}
	char menuInfo[INFOLEN];	
	char menuName[NAMELEN];
	if (action == MenuAction_Cancel)
	{
		if (param2 == MenuCancel_ExitBack) 
		{
			menu.GetItem(0, menuInfo, sizeof(menuInfo));
			int lastPage = StringToInt(menuInfo);
			mapMenu.DisplayAt(param1, lastPage, MENU_TIME_FOREVER);
		}
	}
	else if (action == MenuAction_Select)
	{
		menu.GetItem(param2, menuInfo, sizeof(menuInfo), _, menuName, sizeof(menuName));
		IntToString(menu.Selection, menuInfo, sizeof(menuInfo));
		Menu actionMenu = new Menu(ChangeActionMenuHandler);
	    actionMenu.SetTitle(menuName);
	  	actionMenu.AddItem(menuInfo,"强制更换");
	  	actionMenu.AddItem(menuInfo,"预定");
		actionMenu.ExitButton = true;
		actionMenu.ExitBackButton = true;
		actionMenu.Display(param1, MENU_TIME_FOREVER);
	}
	return 0;
}
 
public int ChangeActionMenuHandler(Menu menu, MenuAction action, int param1, int param2)
{
	if (action == MenuAction_End) 
	{
		delete menu;
		return 0;
	}
	char menuInfo[INFOLEN];	
	char menuName[NAMELEN];
	if (action == MenuAction_Cancel)
	{
		if (param2 == MenuCancel_ExitBack) 
		{
			menu.GetItem(0, menuInfo, sizeof(menuInfo));
			int lastPage = StringToInt(menuInfo);
			levelMenu.DisplayAt(param1, lastPage, MENU_TIME_FOREVER);
		}
	}
	else if (action == MenuAction_Select)
	{
		char nextMapName[NAMELEN];
		menu.GetTitle(nextMapName,NAMELEN);
		menu.GetItem(param2, menuInfo, sizeof(menuInfo), _, menuName, sizeof(menuName));
		if(strcmp(menuName,"强制更换")==0)
		{
			// ForceChangeLevel(nextMapName, "admin Change Map");
			PrintToChatAll("\x04[提示]\x05正在更换地图\x04[\x03%s\x04]...", nextMapName);
			ServerCommand("map %s",nextMapName)
		}
		else
		{
			bsMap.SetString(nextMapName);
			PrintToChatAll("\x04[提示]\x05下一张地图已预定为\x04[\x03%s\x04]", nextMapName);
		}
	}
	return 0;
}

public void OnFinaleWin(Event event, const char[] name, bool dontBroadcast)
{
	char nextMapName[NAMELEN];
	bsMap.GetString(nextMapName,NAMELEN);
	if(IsMapValid(nextMapName))
	{
		ForceChangeLevel(nextMapName, "admin Change Map");
		bsMap.SetString("");
	}
}

